import os
import uuid
from typing import Optional, List, Dict, Any
from moviepy.editor import VideoFileClip, concatenate_videoclips, CompositeVideoClip, ImageClip, ColorClip, VideoClip
import tempfile
import json
from services.llm_service import LLMService
from services.ai_image_generator import AIImageGenerator
from services.audio_service import AudioService
import logging
from PIL import Image, ImageDraw, ImageFont
import numpy as np
import random

logger = logging.getLogger(__name__)

class UnifiedVideoGenerator:
    def __init__(self, llm_service: LLMService):
        self.llm_service = llm_service
        self.ai_image_generator = AIImageGenerator()
        self.audio_service = AudioService()
    
    def generate_video(self, prompt: str, output_path: str, 
                      use_ai_images: bool = True, 
                      enable_audio: bool = True,
                      enable_effects: bool = True):
        """统一的视频生成入口"""
        # 1. 生成脚本
        script = self.llm_service.generate_video_script(prompt)
        
        # 2. 创建场景
        video_clips = self._create_unified_scenes(script, use_ai_images, enable_effects)
        
        try:
            # 3. 合并视频
            final_video = concatenate_videoclips(video_clips, method="compose")
            
            # 4. 添加音频
            if enable_audio:
                final_video = self._add_enhanced_audio(final_video, script)
            
            # 5. 写入文件
            final_video.write_videofile(
                output_path,
                fps=24,
                codec='libx264',
                audio_codec='aac',
                verbose=False,
                logger=None
            )
            
            return True
        finally:
            # 清理资源
            for clip in video_clips:
                clip.close()
            if 'final_video' in locals():
                final_video.close()
    
    def _create_unified_scenes(self, script: dict, use_ai_images: bool, enable_effects: bool):
        """统一创建场景"""
        scenes = []
        
        # 标题场景
        title_scene = self._create_unified_scene(
            script.get("title", "AI生成视频"),
            "title",
            duration=3,
            use_ai_images=use_ai_images,
            enable_effects=enable_effects
        )
        scenes.append(title_scene)
        
        # 其他场景 - 从脚本中获取更多场景信息
        sections = script.get("sections", [])
        for i, section in enumerate(sections):
            scene = self._create_unified_scene(
                section.get("text", f"内容 {i+1}"),
                "content",
                duration=min(section.get("duration", 5), 10),  # 限制最大时长
                use_ai_images=use_ai_images,
                enable_effects=enable_effects
            )
            scenes.append(scene)
        
        # 结尾场景
        conclusion = script.get("conclusion", {})
        if conclusion:
            conclusion_scene = self._create_unified_scene(
                conclusion.get("text", "感谢观看"),
                "conclusion",
                duration=3,
                use_ai_images=use_ai_images,
                enable_effects=enable_effects
            )
            scenes.append(conclusion_scene)
        
        return scenes
    
    def _create_unified_scene(self, text: str, scene_type: str, duration: int, 
                            use_ai_images: bool, enable_effects: bool):
        """统一场景创建"""
        # 背景选择
        if use_ai_images:
            background = self._create_ai_background(text, scene_type, duration)
        else:
            background = self._create_dynamic_background(scene_type, duration)
        
        # 文字层
        if enable_effects:
            text_layer = self._create_animated_text(text, duration, scene_type)
        else:
            text_layer = self._create_static_text(text, duration)
        
        return CompositeVideoClip([background, text_layer])
    
    def _create_ai_background(self, text: str, scene_type: str, duration: int):
        """创建AI生成的背景"""
        try:
            # 尝试使用AI生成背景图像
            if self.ai_image_generator.huggingface_token:
                ai_prompt = f"{text} scene, {scene_type} style, high quality background"
                ai_image = self.ai_image_generator.generate_image_for_scene(ai_prompt, "realistic")
                
                if ai_image:
                    # 调整图像尺寸以适应视频
                    ai_image = ai_image.resize((1280, 720), Image.LANCZOS)
                    background = ImageClip(np.array(ai_image), duration=duration)
                    logger.info("✅ 使用AI生成的背景图像")
                    return background
        except Exception as e:
            logger.warning(f"AI图像生成失败，使用颜色背景: {e}")
        
        # 如果AI图像生成失败，使用颜色背景
        bg_color = self._get_deterministic_color(text)
        return ColorClip(size=(1280, 720), color=bg_color, duration=duration)

    def _create_dynamic_background(self, scene_type: str, duration: int):
        """创建动态背景"""
        try:
            # 根据场景类型选择颜色方案
            color_schemes = {
                "title": [(30, 100), (60, 60, 150)],  # 蓝色系
                "introduction": [(60, 60, 120), (90, 90, 180)],  # 中蓝色系
                "content": [(80, 140), (110, 110, 200)],  # 紫色系
                "highlight": [(120, 80, 80), (150, 110, 110)],  # 红色系
                "conclusion": [(30, 100, 30), (60, 130, 60)],  # 绿色系
            }
            
            colors = color_schemes.get(scene_type, [(100, 100, 200), (130, 130, 230)])
            
            # 创建简单的动态背景（颜色渐变）
            def make_frame(t):
                progress = t / duration
                
                # 在两个颜色之间渐变
                r = int(colors[0][0] + (colors[1][0] - colors[0][0]) * progress)
                g = int(colors[0][1] + (colors[1][1] - colors[0][1]) * progress)
                b = int(colors[0][2] + (colors[1][2] - colors[0][2]) * progress)
                
                frame = np.zeros((720, 1280, 3), dtype=np.uint8)
                frame[:, :] = [r, g, b]
                
                return frame
            
            from moviepy.video.VideoClip import VideoClip
            background = VideoClip(make_frame, duration=duration)
            return background
            
        except Exception as e:
            logger.error(f"❌ 创建动态背景失败: {e}")
            return ColorClip(size=(1280, 720), color=(100, 100, 200), duration=duration)

    def _create_animated_text(self, text: str, duration: int, scene_type: str):
        """创建带动画效果的文本"""
        try:
            # 限制文本长度
            if len(text) > 500:
                text = text[:500] + "..."
            
            # 创建背景图像（透明）
            img = Image.new('RGBA', (1280, 720), (0, 0, 0, 0))
            draw = ImageDraw.Draw(img)
            
            # 加载字体
            font = self._get_font(48)
            
            # 文本分行
            lines = self._split_text_into_lines(text, max_width=1200, font=font)
            
            # 计算总高度和起始位置
            line_height = 55
            total_height = len(lines) * line_height
            start_y = (720 - total_height) // 2
            
            # 根据场景类型应用不同的动画效果
            if scene_type == "title":
                # 标题淡入效果
                opacity = 255
                scale = 1.0
            elif scene_type == "conclusion":
                # 结尾保持显示
                opacity = 255
                scale = 1.0
            else:
                # 内容场景
                opacity = 255
                scale = 1.0
            
            # 绘制每行文字
            for i, line in enumerate(lines):
                bbox = draw.textbbox((0, 0), line, font=font)
                text_width = bbox[2] - bbox[0]
                x = (1280 - text_width) // 2
                y = start_y + i * line_height
                
                # 添加文字阴影（轻微偏移）
                shadow_color = (0, 0, 0, 180)
                draw.text((x+2, y+2), line, font=font, fill=shadow_color)
                
                # 主文字
                text_color = (255, 255, 255, opacity)
                draw.text((x, y), line, font=font, fill=text_color)
            
            # 创建ImageClip并返回
            text_image = np.array(img)
            text_clip = ImageClip(text_image, duration=duration)
            return text_clip
            
        except Exception as e:
            logger.error(f"❌ 创建动画文本失败: {e}")
            # 如果失败，返回简单的文字图像
            return self._create_static_text(text, duration)

    def _create_static_text(self, text: str, duration: int):
        """创建静态文本"""
        try:
            # 限制文本长度
            if len(text) > 500:
                text = text[:500] + "..."
            
            # 创建背景图像
            img = Image.new('RGB', (1280, 720), color=(0, 0, 0))
            draw = ImageDraw.Draw(img)
            
            # 加载字体
            font = self._get_font(48)
            
            # 文本分行
            lines = self._split_text_into_lines(text, max_width=1200, font=font)
            
            # 计算总高度和起始位置
            line_height = 5
            total_height = len(lines) * line_height
            start_y = (720 - total_height) // 2
            
            # 绘制每行文字
            for i, line in enumerate(lines):
                bbox = draw.textbbox((0, 0), line, font=font)
                text_width = bbox[2] - bbox[0]
                x = (1280 - text_width) // 2
                y = start_y + i * line_height
                
                # 添加文字阴影（轻微偏移）
                shadow_color = (0, 0, 0)
                draw.text((x+2, y+2), line, font=font, fill=shadow_color)
                
                # 主文字
                draw.text((x, y), line, font=font, fill=(255, 255, 255))
            
            # 创建ImageClip并返回
            text_image = np.array(img)
            text_clip = ImageClip(text_image, duration=duration)
            return text_clip
            
        except Exception as e:
            logger.error(f"❌ 创建静态文本失败: {e}")
            # 如果失败，返回纯色背景
            return ColorClip(size=(1280, 720), color=(50, 50, 50), duration=duration)

    def _add_enhanced_audio(self, video_clip, script: dict):
        """为视频添加增强音频"""
        try:
            # 生成音频
            audio = self.audio_service.generate_audio_for_video(video_clip.duration, script)
            
            if audio:
                # 设置视频音频
                video_with_audio = video_clip.set_audio(audio)
                logger.info("✅ 音频添加成功")
                return video_with_audio
            else:
                logger.warning("无法添加音频，返回原视频")
                return video_clip
                
        except Exception as e:
            logger.error(f"❌ 添加音频失败: {e}")
            return video_clip

    def _get_font(self, size: int):
        """获取字体 - 带缓存版本"""
        # 限制字体大小范围
        size = max(12, min(72, size)) # 限制在12-72之间
        
        try:
            # 字体路径列表（按优先级排序）
            import os
            current_dir = os.path.dirname(os.path.abspath(__file__))
            font_paths = [
                # 1. 项目本地字体（最高优先级）
                os.path.join(current_dir, "..", "fonts", "simhei.ttf"),      # 黑体
                os.path.join(current_dir, "..", "fonts", "msyh.ttc"),        # 微软雅黑
                os.path.join(current_dir, "..", "fonts", "simsun.ttc"),      # 宋体
                
                # 2. Windows系统字体
                "C:/Windows/Fonts/simhei.ttf",    # 黑体
                "C:/Windows/Fonts/msyh.ttc",      # 微软雅黑
                "C:/Windows/Fonts/msyhbd.ttc",    # 微软雅黑粗体
                "C:/Windows/Fonts/simsun.ttc",    # 宋体
                "C:/Windows/Fonts/simkai.ttf",    # 楷体
                "C:/Windows/Fonts/simfang.ttf",   # 仿宋
                
                # 3. 备用英文字体
                os.path.join(current_dir, "..", "fonts", "arial.ttf"),
                "C:/Windows/Fonts/arial.ttf",
                "C:/Windows/Fonts/times.ttf",
            ]
            
            for font_path in font_paths:
                try:
                    if os.path.exists(font_path):
                        font = ImageFont.truetype(font_path, size)
                        logger.info(f"✅ 加载字体: {font_path}")
                        return font
                except OSError as e:
                    logger.debug(f"字体文件不存在或损坏：{font_path} - {e}")
                    continue
                except Exception as e:
                    logger.debug(f"字体加载异常 {font_path}: {e}")
                    continue
            
            # 如果所有字体都失败，使用默认字体
            logger.warning("所有字体加载失败，使用默认字体")
            return ImageFont.load_default()
            
        except Exception as e:
            logger.error(f"字体加载异常: {e}")
            return ImageFont.load_default()

    def _get_deterministic_color(self, text: str) -> tuple:
        """基于文本生成确定性颜色"""
        # 使用文本的哈希值来生成确定性颜色
        hash_val = hash(text) % 360 # 使用0-359度的色相
        
        # 将HSV转换为RGB
        import colorsys
        r, g, b = colorsys.hsv_to_rgb(hash_val / 360.0, 0.7, 0.8)  # 饱和度0.7，亮度0.8
        
        return (int(r * 255), int(g * 255), int(b * 255))

    def _split_text_into_lines(self, text: str, max_width: int, font):
        """将文本分割成多行"""
        try:
            words = text.split()
            lines = []
            current_line = []
            
            for word in words:
                test_line = ' '.join(current_line + [word])
                
                # 估算文本宽度
                bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).textbbox((0, 0), test_line, font=font)
                text_width = bbox[2] - bbox[0]
                
                if text_width <= max_width:
                    current_line.append(word)
                else:
                    if current_line:
                        lines.append(' '.join(current_line))
                    current_line = [word]
            
            if current_line:
                lines.append(' '.join(current_line))
            
            # 如果行数太多，截断
            if len(lines) > 8:
                lines = lines[:8]
                if len(lines[-1]) > 50:
                    lines[-1] = lines[-1][:47] + "..."
            
            return lines
            
        except Exception as e:
            logger.error(f"❌ 文本分行失败: {e}")
            # 简单的分行作为后备
            return [text[i:i+50] for i in range(0, min(len(text), 400), 50)]
